package com.gzhryc.shared_device.common.device.services;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.common.device.dao.DeviceUpgradeTaskDao;
import com.gzhryc.shared_device.common.device.dao.db.DeviceTypeVersion;
import com.gzhryc.shared_device.common.device.dao.db.DeviceUpgradeTask;
import com.gzhryc.shared_device.common.device.dao.enums.DeviceUpgradeTaskEnum;
import com.gzhryc.shared_device.common.device.dao.models.UpgradeProcessInfo;
import com.gzhryc.shared_device.common.device.services.dto.DeviceUpgradeTaskSearch;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

public class DeviceUpgradeTaskService {

    static Logger log = Logger.getLogger(DeviceUpgradeTaskService.class);

    public static DeviceUpgradeTaskService self() {
        return MultiDBTools.getService(DeviceUpgradeTaskService.class, true);
    }

    public static DeviceUpgradeTaskService self(String jdbcKey) {
        return MultiDBTools.getService(jdbcKey, DeviceUpgradeTaskService.class, true);
    }

    DeviceUpgradeTaskDao dao;

    public DeviceUpgradeTaskService(String jdbcKey) {
        dao = new DeviceUpgradeTaskDao(jdbcKey);
    }

    public List<DeviceUpgradeTask> findJoinBySearch(DeviceUpgradeTaskSearch search, Integer pageNo, Integer pageLimit){
        Conditions conditions = dao.buildConditions(search);
        try {
            return dao.findJoinByCondition(conditions,pageNo,pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public Long countJoinBySearch(DeviceUpgradeTaskSearch search){
        Conditions conditions = dao.buildConditions(search);
        try {
            return dao.countJoin(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return 0L;
    }

    public DeviceUpgradeTask getUpgradingByDeviceSn(String deviceSn){
        if(StringTools.isNotBlank(deviceSn)){
            Conditions conditions = new Conditions(DeviceUpgradeTask.class);
            conditions.and().is("deviceSn",deviceSn);
            conditions.and().is("state", DeviceUpgradeTaskEnum.State.Upgrading.index());
            try {
                return dao.get(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return null;
    }

    public DeviceUpgradeTask getById(Long id){
        try {
            return dao.getById(id);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public DeviceUpgradeTask getJoinById(Long id){
        try {
            return dao.getJoinById(id);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public boolean add(DeviceUpgradeTask deviceUpgradeTask) throws LogicException {
        DeviceTypeVersion deviceTypeVersion = DeviceTypeVersionService.self().getByKeys(deviceUpgradeTask.getDeviceTypeId(),deviceUpgradeTask.getVersionNumber());
        if(deviceTypeVersion == null){
            throw new LogicException("未找到设备固件升级包");
        }

        DeviceUpgradeTask temp = getUpgradingByDeviceSn(deviceUpgradeTask.getDeviceSn());
        if(temp != null){
            throw new LogicException("设备已存在升级任务");
        }

        deviceUpgradeTask.setPackagePath(deviceTypeVersion.getPackagePath());
        deviceUpgradeTask.setPackageCRC(deviceTypeVersion.getPackageCRC());
        deviceUpgradeTask.setCreateDate(new Date());
        try {
            return dao.insert(deviceUpgradeTask) > 0;
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return false;
    }

    public void executeCheck(String deviceSn,String versionNumber){
        if(StringTools.isNotBlank(deviceSn) && StringTools.isNotBlank(versionNumber)){
            Conditions conditions = new Conditions(DeviceUpgradeTask.class);
            conditions.and().is("deviceSn",deviceSn);
            conditions.and().is("versionNumber",versionNumber);
            conditions.and().is("state",DeviceUpgradeTaskEnum.State.Upgrading.index());

            try {
                DeviceUpgradeTask upgradeTask = dao.get(conditions);
                if(upgradeTask != null){
                    UpgradeProcessInfo processInfo = null;
                    if(StringTools.isNotBlank(upgradeTask.getUpgradeProcessInfo())){
                        processInfo = JsonTools.fromJson(upgradeTask.getUpgradeProcessInfo(),UpgradeProcessInfo.class);
                    }else {
                        processInfo = new UpgradeProcessInfo();
                    }
                    UpgradeProcessInfo.Item item = new UpgradeProcessInfo.Item();
                    item.setDate(new Date());
                    item.setNote("设备上线通知版本已更新");
                    processInfo.getItems().add(item);

                    DeviceUpgradeTask updateEntity = new DeviceUpgradeTask();
                    updateEntity.setState(DeviceUpgradeTaskEnum.State.Finish.index());
                    updateEntity.setUpgradeProcessInfo(JsonTools.toJson(processInfo));

                    if(dao.updateNotNull(updateEntity,conditions) <= 0){
                        log.error("修改{{0}}升级任务状态失败",upgradeTask.getId());
                    }
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
    }

    public DeviceUpgradeTask execute(Long id) throws LogicException {
        DeviceUpgradeTask deviceUpgradeTask = getJoinById(id);
        if(deviceUpgradeTask == null){
            throw new LogicException("未找到升级任务");
        }

        if(!DeviceUpgradeTaskEnum.State.WaitExecute.index().equals(deviceUpgradeTask.getState())){
            throw new LogicException("升级任务以执行");
        }

        Conditions conditions = new Conditions(DeviceUpgradeTask.class);
        conditions.and().is("id",id);
        conditions.and().is("state",DeviceUpgradeTaskEnum.State.WaitExecute.index());

        DeviceUpgradeTask updateEntity = new DeviceUpgradeTask();
        updateEntity.setState(DeviceUpgradeTaskEnum.State.Upgrading.index());

        try {
            if(dao.updateNotNull(updateEntity,conditions) > 0){
                deviceUpgradeTask.setState(DeviceUpgradeTaskEnum.State.Upgrading.index());
                return deviceUpgradeTask;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public boolean updateProcessInfo(Long id, UpgradeProcessInfo processInfo){
        if(id != null && processInfo != null){
            DeviceUpgradeTask updateEntity = new DeviceUpgradeTask();
            updateEntity.setId(id);
            updateEntity.setUpgradeProcessInfo(JsonTools.toJson(processInfo));

            try {
                return dao.updateNotNull(updateEntity) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean toFail(Long id,String failNote){
        if(id != null && StringTools.isNotBlank(failNote)){
            DeviceUpgradeTask updateEntity = new DeviceUpgradeTask();
            updateEntity.setId(id);
            updateEntity.setState(DeviceUpgradeTaskEnum.State.Fail.index());
            updateEntity.setFailNote(failNote);

            try {
                return dao.updateNotNull(updateEntity) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean executeFail(DeviceUpgradeTask upgradeTask,String failNote){
        if(upgradeTask != null) {
            UpgradeProcessInfo processInfo = null;
            if(StringTools.isNotBlank(failNote)){
                if(StringTools.isNotBlank(upgradeTask.getUpgradeProcessInfo())){
                    processInfo = JsonTools.fromJson(upgradeTask.getUpgradeProcessInfo(),UpgradeProcessInfo.class);
                }else {
                    processInfo = new UpgradeProcessInfo();
                }
                UpgradeProcessInfo.Item item = new UpgradeProcessInfo.Item();
                item.setDate(new Date());
                item.setNote(failNote);
                processInfo.getItems().add(item);
            }

            DeviceUpgradeTask updateEntity = new DeviceUpgradeTask();
            updateEntity.setId(upgradeTask.getId());
            updateEntity.setState(DeviceUpgradeTaskEnum.State.WaitExecute.index());
            if(processInfo != null){
                updateEntity.setUpgradeProcessInfo(JsonTools.toJson(processInfo));
            }
            try {
                return dao.updateNotNull(updateEntity) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean deleteById(Long id) throws LogicException{
        DeviceUpgradeTask temp = getById(id);
        if(temp == null){
            throw new LogicException("未找到升级任务");
        }
        if(DeviceUpgradeTaskEnum.State.Upgrading.index().equals(temp.getState())){
            throw new LogicException("升级任务升级中，不允许删除");
        }
        try {
            return dao.deleteById(id) > 0;
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return false;
    }
}
